package com.koron.plan.web.patrollineplan.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.koron.plan.web.patrollineplan.bean.dto.PlanLinePatrolEquipment;
import com.koron.plan.web.patrollineplan.bean.dto.PlanLinePatrolItemDTO;
import com.koron.plan.web.patrollineplan.bean.po.PlanLinePatrolCheck;
import com.koron.plan.web.patrollineplan.bean.po.PlanLinePatrolItem;
import com.koron.plan.web.patrollineplan.bean.po.PlanLinePatrolRecord;
import com.koron.plan.web.patrollineplan.mapper.PlanLinePatrolItemMapper;
import com.koron.plan.web.patrollineplan.service.PlanLinePatrolCheckService;
import com.koron.plan.web.patrollineplan.service.PlanLinePatrolItemService;
import com.koron.plan.web.patrollineplan.service.PlanLinePatrolRecordService;
import org.apache.commons.collections4.CollectionUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 线路巡视计划-巡视点(PlanLinePatrolItem)表服务实现类
 *
 * @author jzp
 * @since 2022-11-24 14:24:19
 */
@Service
public class PlanLinePatrolItemServiceImpl implements PlanLinePatrolItemService {

    @Autowired
    private PlanLinePatrolCheckService planLinePatrolCheckService;
    @Autowired
    private PlanLinePatrolRecordService planLinePatrolRecordService;

    /**
     * 通过ID查询单条数据
     */
    @Override
    @TaskAnnotation("getById")
    public PlanLinePatrolItem getById(SessionFactory factory, String id) {
        PlanLinePatrolItemMapper mapper = factory.getMapper(PlanLinePatrolItemMapper.class);
        return mapper.selectById(id);
    }

    /**
     * 查询所有数据
     */
    @Override
    @TaskAnnotation("list")
    public List<PlanLinePatrolItem> list(SessionFactory factory, PlanLinePatrolItem planLinePatrolItem) {
        PlanLinePatrolItemMapper mapper = factory.getMapper(PlanLinePatrolItemMapper.class);
        return mapper.selectList(planLinePatrolItem);
    }

    @Override
    public List<PlanLinePatrolItem> listByPlanId(SessionFactory factory, String planId) {
        PlanLinePatrolItem planLinePatrolItem = new PlanLinePatrolItem();
        planLinePatrolItem.setPlanId(planId);
        return list(factory, planLinePatrolItem);
    }

    @Override
    public List<PlanLinePatrolItemDTO> listDtoByPlanId(SessionFactory factory, String planId) {
        // 查询所有巡视点信息
        List<PlanLinePatrolItem> planLinePatrolItems = listByPlanId(factory, planId);
        if (CollectionUtils.isEmpty(planLinePatrolItems)) {
            return null;
        }

        // 排序
        planLinePatrolItems = planLinePatrolItems.stream().sorted(Comparator.comparingInt(PlanLinePatrolItem::getNoNullSort)).collect(Collectors.toList());
        Map<String, PlanLinePatrolItemDTO> itemDTOMap = planLinePatrolItems.stream()
                .map(e -> BeanUtil.toBean(e, PlanLinePatrolItemDTO.class))
                .collect(Collectors.toMap(PlanLinePatrolItem::getId, e -> e, (o1, o2) -> o1, LinkedHashMap::new));
        // 查询所有检查项信息
        List<PlanLinePatrolCheck> planLinePatrolChecks = planLinePatrolCheckService.listByPlanId(factory, planId);
        if (CollectionUtils.isNotEmpty(planLinePatrolChecks)) {
            planLinePatrolChecks.forEach(check -> {
                PlanLinePatrolItemDTO planLinePatrolItemDTO = itemDTOMap.get(check.getPatrolPointId());
                planLinePatrolItemDTO.addCheck(check);
            });
        }
        // 查询所有数据记录项信息
        List<PlanLinePatrolRecord> planLinePatrolRecords = planLinePatrolRecordService.listByPlanId(factory, planId);
        if (CollectionUtils.isNotEmpty(planLinePatrolRecords)) {
            planLinePatrolRecords.forEach(record -> {
                PlanLinePatrolItemDTO planLinePatrolItemDTO = itemDTOMap.get(record.getPatrolPointId());
                planLinePatrolItemDTO.addRecord(record);
            });
        }

        // 构建返回数据
        // 因为之前是一个巡视点一个巡视设备为一条数据，现在需要修改成一对多的结构返回
        List<PlanLinePatrolItemDTO> value = buildReturnValue(itemDTOMap);
        // 填充数据
        return value;
    }

    private List<PlanLinePatrolItemDTO> buildReturnValue(Map<String, PlanLinePatrolItemDTO> itemDTOMap) {
        return new ArrayList<>(itemDTOMap.values().stream()
                .sorted(Comparator.comparingInt(PlanLinePatrolItemDTO::getNoNullSort))
                .peek(e -> {
                    PlanLinePatrolEquipment planLinePatrolEquipment = BeanUtil.copyProperties(e, PlanLinePatrolEquipment.class);
                    planLinePatrolEquipment.setPatrolPointType(e.getItemValue() == null ? e.getId() : e.getItemValue());
                    e.setEquipmentList(new ArrayList<>(Collections.singletonList(planLinePatrolEquipment)));
                })
                .collect(Collectors.toMap(
                        e -> e.getItemValue() == null ? e.getId() : e.getItemValue(),
                        Function.identity(),
                        (p1, p2) -> {
                            p1.getEquipmentList().addAll(p2.getEquipmentList());
                            return p1;
                        })
                ).values().stream().sorted(Comparator.comparingInt(PlanLinePatrolItemDTO::getNoNullSort)).collect(Collectors.toList()));
    }

    /**
     * 新增数据
     */
    @Override
    @TaskAnnotation("save")
    public boolean save(SessionFactory factory, PlanLinePatrolItem planLinePatrolItem) {
        PlanLinePatrolItemMapper mapper = factory.getMapper(PlanLinePatrolItemMapper.class);
        return mapper.insertOrUpdate(planLinePatrolItem) > 0;
    }

    @Override
    public boolean saveBatch(SessionFactory factory, List<PlanLinePatrolItem> items) {
        if (CollectionUtils.isEmpty(items)) {
            return false;
        }
        PlanLinePatrolItemMapper mapper = factory.getMapper(PlanLinePatrolItemMapper.class);
        return mapper.insertOrUpdateBatch(items) > 0;
    }

    @Override
    public boolean saveDtoBatch(SessionFactory factory, List<PlanLinePatrolItemDTO> itemList, String planId) {
        if (CollectionUtils.isEmpty(itemList)) {
            return false;
        }
        itemList.forEach(e -> e.setId(null));

        // todo
        List<PlanLinePatrolItem> pointList = new ArrayList<>();
        List<PlanLinePatrolItemDTO> pointDtoList = new ArrayList<>();
        AtomicInteger indexType = new AtomicInteger(1);
        itemList.stream().forEach(planLinePatrolItemDTO -> {
            List<PlanLinePatrolEquipment> equipmentList = planLinePatrolItemDTO.getEquipmentList();
            if (planLinePatrolItemDTO.getCategory().equals("equipment") && CollectionUtils.isNotEmpty(equipmentList)) {
                equipmentList.stream().forEach(planLinePatrolEquipment -> {
                    PlanLinePatrolItemDTO newItem = new PlanLinePatrolItemDTO();

                    BeanUtil.copyProperties(planLinePatrolItemDTO, newItem);
                    BeanUtil.copyProperties(planLinePatrolEquipment, newItem, CopyOptions.create().setIgnoreNullValue(true));
                    newItem.setPlanId(planId);
                    newItem.setItemValue(String.valueOf(indexType.get())); //约定：用这个字段作为区分同一个巡视点多个记录的
                    pointList.add(newItem);
                    pointDtoList.add(newItem);
                });
            } else {
                planLinePatrolItemDTO.setPlanId(planId);
                planLinePatrolItemDTO.setItemValue(String.valueOf(indexType.get()));
                pointList.add(planLinePatrolItemDTO);
            }
            indexType.getAndIncrement();
        });

        // 设置排序
        IntStream.range(0, pointList.size()).forEach(i -> pointList.get(i).setSort(i));

        // 保存所有巡视点
//        List<PlanLinePatrolItem> pointList = itemList.stream()
//                .map(e -> BeanUtil.toBean(e, PlanLinePatrolItem.class))
//                .peek(e -> e.setPlanId(planId))
//                .collect(Collectors.toList());
        boolean b = saveBatch(factory, pointList);

        // 给检查项和记录项都设置planId和itemId
        IntStream.range(0, pointDtoList.size()).forEach(i -> {
            pointDtoList.get(i).fillPlanId(planId);
            pointDtoList.get(i).fillItemId(pointList.get(i).getId());
        });
        // 保存检查项和记录项
        List<PlanLinePatrolCheck> checkList = itemList.stream().flatMap(e -> e.listNoNullCheck().stream()).collect(Collectors.toList());
        List<PlanLinePatrolRecord> recordList = itemList.stream().flatMap(e -> e.listNoNullRecord().stream()).collect(Collectors.toList());

        boolean b1 = planLinePatrolCheckService.saveBatch(factory, checkList);
        boolean b2 = planLinePatrolRecordService.saveBatch(factory, recordList);
        return b || b1 || b2;
    }

    /**
     * 修改数据
     */
    @Override
    @TaskAnnotation("update")
    public boolean update(SessionFactory factory, PlanLinePatrolItem planLinePatrolItem) {
        PlanLinePatrolItemMapper mapper = factory.getMapper(PlanLinePatrolItemMapper.class);
        return mapper.update(planLinePatrolItem) > 0;
    }

    /**
     * 通过主键删除数据
     */
    @Override
    @TaskAnnotation("deleteById")
    public boolean deleteById(SessionFactory factory, String id) {
        PlanLinePatrolItemMapper mapper = factory.getMapper(PlanLinePatrolItemMapper.class);
        return mapper.hidden(id) > 0;
    }

    @Override
    public boolean deleteBatchIds(SessionFactory factory, List<String> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        PlanLinePatrolItemMapper mapper = factory.getMapper(PlanLinePatrolItemMapper.class);
        return mapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public boolean removeByPlanId(SessionFactory factory, String planId) {
        if (StringUtils.isEmpty(planId)) {
            return false;
        }
        List<PlanLinePatrolItem> itemList = this.listByPlanId(factory, planId);
        return deleteBatchIds(factory, itemList.stream().map(PlanLinePatrolItem::getId).collect(Collectors.toList()));
    }

    @Override
    public boolean removeDtoByPlanId(SessionFactory factory, String planId) {
        boolean b = this.removeByPlanId(factory, planId);
        boolean b1 = planLinePatrolCheckService.removeByPlanId(factory, planId);
        boolean b2 = planLinePatrolRecordService.removeByPlanId(factory, planId);
        return b || b1 || b2;
    }
}
